package crypto

import (
	"encoding/base64"
	"encoding/hex"
	"fmt"
	"gitee.com/zhouhailin/hutool-go/hutool/crypto/sm"
	"gitee.com/zhouhailin/hutool-go/hutool/crypto/sm3"
	"gitee.com/zhouhailin/hutool-go/hutool/crypto/sm4"
)

func (_sm CryptoUtil) SM3(bytes []byte) string {
	return fmt.Sprintf("%x", sm3.Sum(bytes))
}

func (_sm CryptoUtil) SM3Str(str string) string {
	return fmt.Sprintf("%x", sm3.Sum([]byte(str)))
}

func (_sm CryptoUtil) EncryptSM4(in []byte, key []byte) ([]byte, error) {
	plainTextWithPadding := sm.PKCS5Padding(in, sm4.BlockSize)
	encrypt, err := sm4.ECBEncrypt(key, plainTextWithPadding)
	if err != nil {
		return nil, err
	}
	return encrypt, nil
}

func (_sm CryptoUtil) EncryptSM4Base64(in []byte, base64Key string) (string, error) {
	key, err := base64.StdEncoding.DecodeString(base64Key)
	if err != nil {
		return "", err
	}
	encryptSM4, err := _sm.EncryptSM4(in, key)
	if err != nil {
		return "", err
	}
	return base64.StdEncoding.EncodeToString(encryptSM4), nil
}

func (_sm CryptoUtil) EncryptSM4Base64Str(in string, base64Key string) (string, error) {
	encryptSM4, err := _sm.EncryptSM4Base64([]byte(in), base64Key)
	if err != nil {
		return "", err
	}
	return encryptSM4, nil
}

func (_sm CryptoUtil) EncryptSM4Hex(in []byte, hexKey string) (string, error) {
	key, err := hex.DecodeString(hexKey)
	if err != nil {
		return "", err
	}
	encryptSM4, err := _sm.EncryptSM4(in, key)
	if err != nil {
		return "", err
	}
	return hex.EncodeToString(encryptSM4), nil
}

func (_sm CryptoUtil) EncryptSM4HexStr(in string, hexKey string) (string, error) {
	encryptSM4, err := _sm.EncryptSM4Hex([]byte(in), hexKey)
	if err != nil {
		return "", err
	}
	return encryptSM4, nil
}

func (c CryptoUtil) DecryptSM4(in []byte, key []byte) ([]byte, error) {
	decryptWithPadding, err := sm4.ECBDecrypt(key, in)
	if err != nil {
		return nil, err
	}
	return sm.PKCS5UnPadding(decryptWithPadding), nil
}

func (_sm CryptoUtil) DecryptSM4Str(src string, base64Key string) (string, error) {
	var in []byte
	key, err := base64.StdEncoding.DecodeString(base64Key)
	if err != nil {
		return "", err
	}
	if isHexStr(src) {
		in, err = hex.DecodeString(src)
		if err != nil {
			return "", err
		}
	} else {
		in, err = base64.StdEncoding.DecodeString(src)
		if err != nil {
			return "", err
		}
	}
	decryptSM4, err := _sm.DecryptSM4(in, key)
	if err != nil {
		return "", err
	}
	return string(decryptSM4), nil
}
